#include "infodisplay.h"

#include <GL/gl.h>
#include <sstream>
#include <iostream>
#include <iomanip>

using namespace std;

InfoDisplay::InfoDisplay()
: m_Volume(100)
, m_Progress(0.f)
, m_TextScale(1.f)
, m_TextHeight(0.f)
, m_Width(0.f)
, m_Height(0.f)
, m_UnitHeight(0.f)
, m_Margin(0.f)
, m_Spacing(0.f)
{
    string fontPath = DATADIR"/glover/fonts/arial.ttf";
    m_pFont = new FTGLPolygonFont(fontPath.c_str());

    if (m_pFont->Error())
    {
        cerr << "Failed to open font: " << fontPath << endl;
        delete m_pFont;
        m_pFont = NULL;
    }
    else
    {
        m_pFont->FaceSize(1);
    }
}

InfoDisplay::~InfoDisplay()
{
}

void InfoDisplay::setSize(int width, int height)
{
    m_Width         = static_cast<float>(width);
    m_Height        = static_cast<float>(height);

    m_Margin        = m_Width / 30.f;
    m_Spacing       = m_Margin / 2.f;
    m_UnitHeight    = (m_Height - (m_Spacing * 4.f)) / 3.f;

    m_ProgressBar.setDimensions(m_Width - (m_Margin * 2.f), m_UnitHeight);
    setTitle(m_Title);
}

void InfoDisplay::render()
{
    glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT | GL_MULTISAMPLE_BIT_ARB);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glPushMatrix();

    // background
    glBegin(GL_QUADS);
        glColor4f(0.7f, 0.7f, 0.7f, 0.8f);
        glVertex2f(0.f, 0.f);
        glVertex2f(m_Width, 0.f);
        glColor4f(0.7f, 0.7f, 0.7f, 0.2f);
        glVertex2f(m_Width, m_Height);
        glVertex2f(0.f, m_Height);
    glEnd();

    glTranslatef(m_Margin, m_Spacing, 0.f);
    glEnable(GL_MULTISAMPLE_ARB);

    if (m_pFont)
    {
        glPushMatrix();
            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            glScalef(m_TextScale, m_TextScale, 0.f);
            m_pFont->Render(m_Title.c_str());
        glPopMatrix();

        glTranslatef(0.f, (m_TextHeight * m_TextScale) + m_Spacing, 0.f);

        glPushMatrix();
            string info = m_CurrentTime + " / " + m_TotalTime;

            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            glScalef(m_TextScale, m_TextScale, 0.f);
            m_pFont->Render(info.c_str());
        glPopMatrix();
    }
    glDisable(GL_MULTISAMPLE_ARB);

    glTranslatef(0.f, (m_TextHeight * m_TextScale) + m_Spacing, 0.f);

    m_ProgressBar.setProgress(m_Progress);
    m_ProgressBar.render();

    glPopMatrix();

    glPopAttrib();
}

void InfoDisplay::setVolume(int volume)
{
    m_Volume = volume;
}

void InfoDisplay::setCurrentTime(float curTime)
{
    m_CurrentTime = convertSecondsToTimeFormat(curTime);
}

void InfoDisplay::setTotalTime(float totalTime)
{
    m_TotalTime = convertSecondsToTimeFormat(totalTime);
}

void InfoDisplay::setProgress(float progress)
{
    m_Progress = progress;
}

void InfoDisplay::setTitle(const string& title)
{
    // strip path
    size_t pos = title.find_last_of("/\\");
    if (string::npos == pos)
    {
        m_Title = title;
    }
    else
    {
        m_Title = title.substr(pos + 1, title.size() - 1);
    }

    float llx, lly, llz, urx, ury, urz;

    if (m_pFont)
    {
        m_pFont->BBox(m_Title.c_str(), llx, lly, llz, urx, ury, urz);

        m_TextHeight = ury - lly;
        float textWidth = urx - llx;
        float textSpaceAspect = (m_Width - (m_Margin * 2)) / m_UnitHeight;
        float textAspect = textWidth / m_TextHeight;

        if (textAspect < textSpaceAspect)
        {
            m_TextScale = m_UnitHeight / m_TextHeight;
        }
        else
        {
            m_TextScale = (m_Width - (m_Margin * 2)) / textWidth;
        }
    }
}

string InfoDisplay::convertSecondsToTimeFormat(float seconds)
{
    int hours = (int) (seconds / 3600);
    seconds -= hours * 3600;

    int minutes = (int) (seconds / 60);
    seconds -= minutes * 60;

    stringstream ss;
    ss << setw(2) << setfill('0') << hours << ":";
    ss << setw(2) << setfill('0') << minutes << ":";
    ss << setw(2) << setfill('0') << (int) seconds;

    return ss.str();
}
